home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Best of Shareware
/
Best of PC Windows Shareware 1.0 - Wayzata Technology (7111) (1993).iso
/
mac
/
ZIPPED
/
DOS
/
DATABASE
/
PDOXLIB.ZIP
/
MANUAL.DOC
< prev
next >
Wrap
Text File
|
1993-01-09
|
76KB
|
4,820 lines
INTRODUCTION
Welcome to PDOXLIB!
PDOXLIB is a collection of nearly 70 Paradox routines written
entirely in PAL Version 4.0.
The routines range from the simple to the complex and from the
workhorses to the fun.
You'll find lots of routines that prompt the user for information
in different ways. You'll find routines that format data and ones
that remove or replace unwanted characters.
But you'll also find a handy gauge routine that keeps the user
informed of the progress of your calculations. A crawl routine
prints an attractive message across the bottom of the screen.
There's even a pop-up calendar written entirely in PAL! Few busy
programmers would take the time to write such a routine, but it's
the type of finishing touch that adds class and convenience to
your hard-working application.
PDOXLIB routines can be used as is or the source code can be
modified to meet your own needs. The code is liberally commented,
so making your own changes is easy.
But remember, PDOXLIB is shareware. If you use it you have a
responsibility to pay for it. There are plenty of good reasons to
register PDOXLIB, but the point of shareware is to give you the
chance to try out the software and see if it meets your needs. If
so, then it's time to put the check in the mail.
WHY SHOULD I REGISTER PDOXLIB?
The best reason to register PDOXLIB is that it's the right thing
to do. Hard work went into the creation of PDOXLIB and just as
you wouldn't want your work stolen, neither does the author of
PDOXLIB.
But from a practical standpoint, why not register it? The cost is
only $30. Compared to the cost of writing one or two of these
routines yourself, it's downright cheap.
The source code alone is worth the price. You may also find you
love one of the routines, but hate the choice of colors. With the
source code, the full range of available colors is open to you.
From a practical standpoint, you'll find the PDOXLIB library to
be quite large. In fact, it's really too large for practical use.
Adding the library to an existing application would slow your
program down as the computer searches through another 100,000
bytes looking for a routine.
1
With the source code, you add only the routines you need to your
libraries and keep your programs running at their peak speeds.
So put PDOXLIB through its paces and if it works for you, then
drop a check in the mail.
We'd also welcome your comments, suggestions for changes in the
routines or requests for new routines.
And if you don't like a routine, tell us that too. We want
PDOXLIB to be a helpful addition to your toolbox.
January 1993
2
How do I make PDOXLIB work?
First copy all the PDOXLIB files into their own directory. Next,
play the MAKELIB.SC script. The MAKELIB.SC script compiles all
the other scripts into a library. You can then call the routines
as procedures from the library.
The scripts are password protected and are designed to write
their contents to a library, then release themselves from memory.
Upon registration, you are given the password that opens the
script to you for use.
To call the routines from the library, first declare PDOXLIB as
your autolib with the following declaration: autolib = "PDOXLIB",
assuming PDOXLIB is in the current directory. This may be called
from a script or a miniscript.
The following pages give you the syntax for calling each of the
PDOXLIB routines. Use this syntax to call the routines.
3
atprint
Description: Prints a string of text in a specified attribute at
a row and column position on the canvas.
Syntax: atprint.u(text.a, attrib.n, row.n, col.n)
Where: text.a . . is the text to be printed
attrib.n . is the attribute number for the text.
row.n . . . is the row where the text is to be printed.
col.n . . . is the column where the text is to be
printed.
While any beginning PAL programmer can handle the writing of this
code, this routine provides a code-reusable way of handling a
regular chore. The advantage of this routine is that is allows
you to specify the color attribute of the text to be printed.y
4
bgetdate
Description: Prompts the user for a date via the dialog box. The
procedure uses PAL's ACCEPT statement for getting data.
Syntax: newdate.d = bgetdate.d ()
Where: newdate.d . receives a new, valid date
This routine pops a dialog box into the center of the screen and
prompts the user to enter a day in the MM/DD/YY format. Because
ACCEPT is used, only a valid date may be entered.
5
bgetphone
Description: Prompts the user for a telephone number via a dialog
box on the screen. It uses the PAL ACCEPT command and requires an
area code entry. The routine returns a string in the format: NNN-
NNN-NNNN.
Syntax: phonenumber.a = bgetphone.a ()
Where: phonenumber.a receives a formatted telephone number
Although Paradox provides validation checks for field data entry,
there are times, such as when prompting for query information,
where a dialog box is helpful. This routine pops a box onto the
center of the screen and prompts the user to enter a telephone
number in the NNN-NNN-NNNN format.
6
bgetssn
Description: Prompts the user for a social security number via a
dialog box on the screen. It uses the PAL ACCEPT command. The
routine returns a string in the format: NNN-NN-NNNN.
Syntax: ssn.a = bgetssn.a ()
Where: ssn.a . . . receives a formatted social security number
Although Paradox provides validation checks for field data entry,
there are times, such as when prompting for query information,
where a dialog box is helpful. This routine pops a box onto the
center of the screen and prompts the user to enter a social
security number in the NNN-NN-NNNN format.
7
calcage
Description: Using a date of birth, the routine returns the
person's age.
Syntax: currentage.n = calcage.n (dob.d)
Where: dob.d . . . is a date variable representing the
person's date of birth.
currentage.n receives the age calculated from the date
of birth
The routine can be used when an age instead of a date is needed.
It can also be used to fill in an age field if only a date of
birth field exists. If procedures are allowed in forms in future
versions of Paradox, the routine might also be useful to keep an
accurate running age of a person when only the date of birth is
available.
8
checkprinter
Description: Checks to see if the printer is ready to receive
text.
Syntax: ready.l = checkprinter.l ()
Where: ready.l . . receives true if the printer is ready and
false if the user wishes to quit.
While the programmer can easily us PAL's PRINTERSTATUS function
to check the printer, you must still deal with the results of
that decision.
The routine does this by quickly returning true if the printer is
ready. If it is not, a dialog box is presented to the user who
can fix the problem, click OK and continue. The user may also
decide to press ESC or CANCEL and abort the decision to print.
The routine gives the programmer a one-stop place to check on the
printer before moving on.
Note that the routine does not deal with printer problems once
printing has begun. Those errors are generally handled by an
error handling routine. The errorlog routine provided with
PDOXLIB is designed to handle those problems.
You should also note that the PRINTERSTATUS function is erratic
at best. You should throughly test the routine on your hardware
before trusting that function or this routine.
Printer problems are often best handled by the ERRORPROC
procedure. The PDOXLIB ERRORLOG routine provides this service.
For more information on setting the ERRORPROC system variable,
consult your Paradox manuals.
9
comparestruct
Description: Compares the structure of two tables to see if they
are identical.
Syntax: test.l = comparestruct.l (table1.a, table2.a)
Where: test.l . . is set to true if they are equal, false if
they are not
table1.a . is the name of the first table
table2.a . is the table to compare to the first table
Often when doing queries or copying reports or forms, you need to
know if two tables have compatible structures. The routine
provides an easy way to do the comparison.
10
copyfamily
Description: Copies just Paradox families members from one table
to another.
Syntax: copyfamily.u (sourcetable.a, targettable.a)
Where: sourcetable.a is the table hosting the family members
targettable.a is the table to receive the family members
It's the command that Borland forgot! While PAL provides easy
ways of copying forms and reports among tables, it does not allow
for copying of just the family members without explicit menu
calls. This routines does just that.
The routine assumes the structure of the two tables is identical.
If you are in doubt, use the comparestruct function to find out.
That routine could have been included here to bullet-proof the
routine, but that would slow down the process considerably --
especially when it may not be necessary.
The routine gives you the most speed possible and if you need to
check for compatibility, simply call the verifying routine.
11
crawl
Description: Displays a message that crawls across the bottom of
the screen to let the user know that work is in progress.
Syntax: crawl.u(message.a)
Where: message.a . is the message to be displayed on the craw
Crawl is intended to a included in a loop such as WHILE or FOR.
With each pass through the loop the program determines the
current position of the message and advances it one column.
For example:
While true
crawl.u("Processing data")
....
....
....
Endwhile
While the program is relatively speedy, it does include a short
pause to make the message readable. For short processing times,
the routine should not pose a problem, but if the loop is
expected to take some time, crawl.u will probably provide too
much of a delay.
12
delrec
Description: A routine to delete the record currently hosting
the cursor.
Syntax: delrec.u ()
The routine will delete the current record after prompting the
user to confirm that choice. The routine can be called from main,
edit or coedit modes. If called in main mode, the routine will
return the user to main mode at the conclusion.
One advantage of the routine is that is saves the most recently
deleted record in memory. By using the companion routine,
saverec.u, the record can be restored. This is true even if the
deletion was made in coedit mode, the edit session was ended with
F2 and the table was removed from the screen.
Only the most recent deletion is held in memory and that is lost
when the user exits Paradox.
13
errorlog
Description: An error procedure that writes system data to a
Paradox table and writes variables to a file. The file name is
then stored in the table.
Syntax: errorproc = "errorlog.u"
Errorlog is intended to provide a paper trail of problems that
might occur with an application.
For a programmer called in to handle unusual problems, the
errorlog table can give the state of the system whenever an error
occurred. Since the data is written to a Paradox table, it can
accommodate a great deal of information over a long period of
time.
Unlike other errorprocedures, errorlog also handles printer
problems. If a printer times out, the procedure will halt until
the user resolves the problem, then returns control to the
printing routine.
14
evenodd
Description: Returns "E" or "O" telling whether a number is even
or odd.
Syntax: result.a = evenodd.a(test.v)
Where: result.a . receives "E", "O" or "Error"
test.v . . is the number to be examined
The routine will accept a number either as a string or in numeric
format and return "E" or "O" to indicate if the number is even or
odd.
If the value tested is not entirely numeric (such as in "326B"),
"Error" is returned.
The routine will work for dates if the value is in the MM/DD/YY
format.
15
exitbox
Description: Uses a dialog box to confirm that the user wishes
to exit the program.
Syntax: confirm.l = exitbox.l ()
Where: confirm.l . returns true if the user wishes to exit
The routine places a dialog box in the center of the screen that
asks the user if he or she wants to exit the program.
16
findB
Description: Searches through a string backwards looking for a
substring.
Syntax: position.n = findB.n(source.a, find.a, start.n)
Where: position.n receives the location of the substring
source.a . is the string to be searched
find.a . . is the string to find in source.a
start.n . . is the position from which to start the
search
PAL's SEARCH and SEARCHFROM functions will search through a
string starting at the beginning looking for a substring. However
sometimes you may wish to start from the back of the string. This
routine provides that capability.
Like SEARCH and SEARCHFROM, it returns the position as counted
from the start of the string. The routine is case insensitive.
If start.n is left blank, the routine assumes you want the entire
string searched.
17
findtable
Description: Searches through a string looking for the first
occurrence of a string listed in the table variable.
Syntax: position.n = findtable.n(start.n, source.a, table.a)
Where: position.n receives the position of the found string
start.n . . is the position in source.a to begin the
search
source.a . is the string to be searched
table.a . . is the table holding the strings to find
In some applications, such as those where you are cleaning data,
you may wish to remove or change several characters at once to
avoid repeated passes through a database. This routine allows you
to create a table of characters you wish to examine and locate
them within a string.
It should be noted the routine only finds the first occurrence of
one of the characters in the table variable. For that reason, you
may wish to call the routine from a loop and continue the
examination until you receive a zero to ensure all characters
were found.
When creating the table.a variable, no separators are required.
For example if you wanted to find all of the punctuation
characters created by the top row of the keyboard, your table.a
variable declaration would look like:
table.a = "!@#$%^&*()"
If no start position is declared, the routine assumes you want to
start at the beginning of the string. The routine is case
insensitive.
18
findtableB
Description: The routine acts exactly like the findtable.n ()
routine except that it begins at the end of a string and works
backwards.
Syntax: position.n = findtableB.n(start.n, source.a, table.a)
Where: position.n receives the position of the found string
start.n . . is the position in source.a to begin the
search
source.a . is the string to be searched
table.a . . is the table holding the strings to find
See the instructions for the findtable routine for instructions
on how the routine works.
19
fullname
Description: Returns the full path name of the current
directory.
Syntax: pathname.a = fullname.a(filename.a, styl.n)
Where: filename.a is the name of a selected file in the
current directory
styl.n . . selects single or double backslashes
pathname.a receives the full path name
When changing directories within an application, it is often
useful to retain valid path names for calling tables or reports
later. This utility allows you to capture that information in a
variable.
Instead of the filename.a, the user can use the PAL function
TABLE (). The routine will then return the full path name of a
table, but without the .DB file extension. Of course the table
must be on the workspace for the TABLE () function to work
properly.
Some Paradox functions also require a double backslash in which
to work properly. By entering a value of zero, the function will
return the path with double backslashes. Any other value will
return single backslashes.
20
getdate
Description: Prompts the user for a date at the current cursor
position.
Syntax: newdate.d = getdate.d()
Where: newdate.d . receives a date variable in the MM/DD/YY
format
Using the ACCEPT command, getdate.d prompts the user for a date.
Care must be taken before calling getdate.d to place the cursor
in the correct position. The routine offers a plain vanilla way
of getting a date. For a more elegant way, see getdate2.
21
getdate2
Description: A more visual way of getting a date from the user
at the current cursor position.
Syntax: newdate.d = getdate2.d ()
Where: newdate.d . receives a date variable in the MM/DD/YY
format
Unlike getdate.d, getdate2.d provides an image on the screen for
the user to complete. By providing that image, it helps the user
determine how the date should be entered. The routine checks to
see if the date is valid before allowing the user to leave,
however the user may press ESC to leave the routine. If so, the
routine returns "ESC" to newdate.d.
22
getnum
Description: Prompts the user to enter a number at the current
cursor location.
Syntax: newnumber.n = getnum.n ()
Where: newnumber.n receives a number typed in by the user.
This is a simple ACCEPT version of getting a number from the
user. Since the style or format of the number is unknown, no
formatting or validity checking can be done. If the user leaves
the routine without entering a number or by pressing ESC, the
routine returns false.
23
getphone
Description: Prompts the user for a telephone number at the
current cursor position.
Syntax: newnumber.a = getphone.a ()
Where: newnumber.a receives a telephone number in the ###-###-
#### format.
The routine uses PAL's ACCEPT command to return a telephone
number.
24
getphone2
Description: Provides a more visual way of prompting the user
for a telephone number at the current cursor location.
Syntax: newnumber.a = getphone2.a ()
Where: newnumber.a receives a telephone number in the ###-###-
#### format.
getphone2.a provides a more visual way to prompt the user for a
telephone number. The routine requires numeric input, but will
return ESC if the user escapes out of the routine. The routine
could be easily modified to allow a default area code, thus
speeding data entry.
25
getssn
Description: Provides a simple way of prompting the user to
enter a social security number at the present cursor location.
Syntax: ssn.a = getssn.a ()
Where: ssn.a . . . receives a social security number in the
###-##-#### format.
Using PAL's accept command, this routine provides a quick way of
getting a social security number. ESC is returned if the user
escapes out of the routine.
26
getssn2
Description: Provides a more visual way of prompting the user to
enter a social security number at the current cursor location.
Syntax: ssn.a = getssn2.a ()
Where: ssn.a . . . receives a social security number in the
###-##-#### format.
Provides a more visual way of prompting the user for a social
security number. The routine puts an image of the number in the
current cursor location and accepts numbers from the user. ESC is
returned if the user presses the escape key.
27
gettext
Description: Gets a line of text at the current cursor location
and formats it to all upper case, lower case or capitalizing the
first letter of each word.
Syntax: newtext.a = gettext.a(length.n, styl.n)
Where: newtext.a . receives a formatted string of text
length.n . is the maximum length of the string
styl.n . . is 1, 2 or 3 to indicate the style desired
The routine prompts the user to input a string of text at the
current cursor location. If the user exits the routine without
entering text or by pressing ESC, the routine returns false.
The length.n variable tells the routine how much text should be
received from the user. The styl.n variable should be set to 1 if
the text is to be returned in all capitals, 2 if it is to be all
lower case or 3 if the first letter of each word is to be
capitalized. If any other value is entered, the string is
returned unaltered.
The routine also calls the lrtrim.a routine to ensure that
newtext.a receives a string without leading or trailing spaces.
28
hrs2days
Description: Designed as a companion routine to timeadd.a,
hrs2days returns the number of days and hours represented by a
time variable.
Syntax: days&time.a = hrs2days.a(timeval.a)
Where: days&time.a is the calculated days and time
timeval.a . is the time to be evaluated.
Following the addition of two time values, the result may extend
past one day. This routine was designed to turn those hours into
days should the hour value not be appropriate.
hrs2days is unique in that it returns two values within one
variable. For example, if hrs2days was asked to evaluate the time
value of 25:00:00, it would return a string that looked like:
1 01:00:00
That's one day, plus one hour.
The string can be broken apart using the SUBSTR routine, but it
can be handled much more elegantly with the MATCH routine.
Using MATCH would look like:
test.l = MATCH(hrs2days.a("25:00:00"), ".. ..", days.a,
time.a)
In this example, MATCH looks for space, as indicated by the
second parameter, within the string returned by hrs2days. When it
finds the space, everything to its left goes into days.a while
everything to its right goes into time.a. The variable test.l
receives true if the space was found, false if it was not.
This routine will always return a value in the day position, even
if the time given it to evaluate is less than a day. If the time
is less that one day, the value will be zero.
29
incre
Description: Increments a string by one value.
Syntax: newvalue.a = increment.a("oldvalue.a")
Where: newvalue.a is the new value of the string
oldvalue.a is the current value of the string
The routine takes a string that is any mix of numbers and letters
and increments it by one. The routine is particularly useful for
incrementing key fields.
30
insertrec
Description: Allows the user to enter a new record.
Syntax: insertrec.u ()
The routine works from main, edit or coedit modes and opens a new
record for the user to enter.
The routine puts the new record into a WAIT RECORD and prompts
the user to press F2 when the entry is complete. The routine also
traps for DOS and DOSBIG to prevent accidental use of those
commands.
31
isdatevalid
Description: Checks a date to see if it is valid.
Syntax: testdate.l = isdatevalid.l(date2test.a)
Where: testdate.l receives true if the date is good or false
if it is not.
date2test.d is the date to be examined
The routine takes a string of text entered in a valid Paradox
date format and checks to see if it is a valid date.
Often data entry routines, such as the getdate2.d routine in this
package, gathers the date as a string, then converts it to a
date. Although the date routines in this package check for valid
dates, this routine could be useful if you used other ways to get
date information.
The routine returns a true if the date is valid and false if it
is not.
It is important that the date be passed to the routine as a
quoted string or in a string variable. Use of the STRVAL()
function will fail if the date is not valid and cause a script
error.
32
keygen1
Description: Generates a random number of up to five digits for
use as a key. Routine also checks key field to make sure key
number is not in use.
Syntax: newkey.n = keygen1.n ()
Where: newkey.n . receives a unique number that can be used
as a key
When the nature of the key is not important, keygen1.n can
provide a unique number quickly and easily.
The routine can be called from any field and will search the key
field to see if the number generated exists. If it does exist,
the routine will continue generating numbers until it finds one
not in use.
The routine makes no network provisions, so care should be taken
to lock the number into the field as soon as it is returned as
possible.
33
keygen2
Description: Generates a number one larger than the largest
number in the key field.
Syntax: newkey.n = keygen2.n(field.a)
Where: newkey.n . receives a number one larger than the
largest in the key field.
field.a . . is the name of the key field in the current
table
The routine can be called from any field and will find the
largest number in the key field, increment it by one and return
it as the new key.
No network provisions are provided in this routine, care should
be taken to lock the number into the table immediately after the
number is returned.
If no number is in the key field, the program returns 100000.
Nearly 900,000 records can be handled in this way.
34
lastfirst
Description: Takes a name in the form of John Doe and returns
Doe, John.
Syntax: newname.a = lastfirst.a (fullname.a)
Where: newname.a . is the last name followed by a comma and
the first name
fullname.a is the full name to be affected
The routine will handle name suffixes such as Jr., Sr., II, III
or IV.
35
lastlast
Description: Takes a name in the form of Doe, John and returns
John Doe.
Syntax: newname.a = lastlast.a(fullname.a)
Where: newname.a . is the full name of the person
fullname.a is the name in last first form
The routine makes allowances for middle initials and simply
searches for the comma. Once the comma is found, the new name is
built accordingly.
36
lrtrim
Description: Trims leading and trailing blanks from a string.
Syntax: newstring.a = lrtrim.a(teststring.a)
Where: newname.a . is a string with leading and trailing
blanks removed
teststring.a is a string that may contain leading or
trailing blanks
Particularly when importing fixed length data, blanks can be part
of the string. This routine is used to remove those ASCII 32
characters.
The routine can be part of a PAL program or can be used within a
scan loop in a miniscript to clean up data in a table.
37
ltrim
Description: Trims leading blanks from a string
Syntax: newname.a = ltrim.a(teststring.a)
Where: newname.a . is a string with leading blanks removed
teststring.a is a string that may contain leading blanks
The routine removes all ASCII 32 characters from the front of a
string. When only leading blanks exist, the use of ltrim.a will
be faster than lrtrim.a.
38
msgline
Description: Puts a highlighted bar on line 24 of the screen and
centers the message on that line.
Syntax: msgline.u(message.a)
Where: message.a . is the string to be displayed
The routine provides a way of giving the user information about
what the program is doing.
39
namekey
Description: Generates a unique key based on the first and last
name of a person.
Syntax: newkey.a = namekey.a()
Where: newkey.a . receives a unique key based on a first and
last name.
One of the problems with a numeric key is that it does not sort
the names alphabetically. That means users have no clue as to
where a name will occur in a database and must constantly use
locate commands.
The namekey.a routine assumes there are two fields in the current
table named "last name" and "first name." From those it
constructs key of no more than 12 characters.
The key takes the first eight letters of the last name and the
first four letters of the first name and puts them together. In
most cases this will provide an accurate sorting. The problem
comes when two people of the same name are entered into the
database.
To defeat this problem, the routine goes to the first field in
the database -- always the key field -- and checks to see if the
newly created key exists. If so, it generates a random two-digit
number and replaces the last two characters of the name field
with it.
For example, if you have a person in your database by the name of
Howard Johnston, the original key would be: JohnstonHowa. If a
second Howard Johnston were added, the key might look like:
Johnst24Howa.
While this could cause some alphabetizing problems, the solution
would be to have a key field wide enough to accommodate any
possibility. Since Paradox works best with narrow tables, the
routine was set for a maximum of 12 characters. This still allows
for up to 100 people (00 through 99) with the same name.
The routine makes no provision for network use and can only be
called after the last name and first name fields have been
filled. Care should be taken to post the key as soon as possible
after the routine has been called to avoid potential conflicts on
a network.
Changes can easily be made in the source code in case the last
name and first name fields have different names.
40
noise
Description: Nine different noises intended to attract the user's
attention.
Syntax: noise.u(n)
Where: n . . . . . is a number 1 through 9
Although PAL's BEEP command can be an effective attention-getter,
at times something else may be needed. The programmer may also
prefer a different sound to let the user know some action has
been completed or to draw their attention to a message.
This routine offers nine such sounds. The first four are quick
attention getters. Five and seven are short sliding sounds while
six simulates a European siren.
Eight and nine are different pitched beeps that continue until
the user presses a key. These are intended to be used when the
user's immediate attention is required.
41
nth_rec
Description: Selects every nth record from a database, places
them in a separate table then deletes them from the original
database.
Syntax: success.l = nth_rec.l(spacing.n)
Where: success.l . receives a true or false indicating the
success of the routine
spacing.n . is the desired nth count
In direct mail and other applications it may be desirable to
select every nth record in a file. The routine plucks those
records out.
The source code can be easily edited to remove those records from
the original file. Comments in the code show how this is done.
42
num2time
Description: Converts a number representing the number of
milliseconds since midnight to a standard HH:MM:SS format.
Syntax: time.a = num2time.a(milliseconds.n)
Where: time.a . . receives the time in a HH:MM:SS format
milliseconds.n is the time since midnight in milliseconds
The Paradox TICKS () function returns the time since midnight in
milliseconds. To make sense of the number it must be converted to
a more readable format. This routine handles that chore.
It also has a companion routine, TIME2NUM, which converts the
standard time format to a number. This is particularly useful
when time needs to be stored in a table. In this way it can be
stored as a 2-byte number instead of an 8-byte string.
43
numbox
Description: Puts a dialog box with headline on the screen so
the user can enter a number.
Syntax: newnumber.n = numbox.n(headline.a)
Where: newnumber.n receives the number entered by the user
headline.a is the headline to put on the box
The routine puts a dialog box on the screen and allows the user
to enter a number. Space for a headline is provided to prompt the
user for what number to enter. The box is sized to accommodate
the length of the headline.
44
numonly
Description: Searches through a string and removes any character
that is not a number except a period.
Syntax: newnumber.n = numonly.a(numberstring.a)
Where: newnumber.n receives a number as a string variable
numberstring.a is a string which may contain both letters
and numbers
There are times when non-numerical data needs to be stripped out
so that a number can be placed either into a numeric variable or
a numeric field.
The numonly.a routine strips out all string values except
periods. A change in the source code can allow for the stripping
of periods also.
An example of this use might be to strip the dashes out of a
telephone number or social security number so the data can be
stored in a smaller numeric field. Of course the dashes would
have to be reinserted when the data is read, but the savings in
disk space may be worth the extra processor time in doing so.
Note that the routine returns the data as a string. It can easily
be converted to a number with the PAL NUMVAL function.
45
okbox
Description: Uses a dialog box to pass a one line message to the
user. The user presses and OK button to return to the program.
Syntax: okbox.u(headline.a, message.a)
Where: headline.a is the headline for the box
message.a . is the message to display in the box.
The routine provides an easy way to present a one line message to
the user and halt program execution until the user acknowledges
the box.
46
parse
Description: A routine to break a string into individual parts.
Syntax: count.n = parse.n(string.a, delimiter.a)
Where: count.n . . receives the number of array elements
string.a . is the string to be parsed
delimiter.a what separates each element or field
Parse will break a string into individual pieces based on
whatever delimited is passed.
An example of how it can be used is the postal routine included
in this package.
Parse is used to break an address into pieces so the postal
routine can examine each one and make corrections.
Another example would be to prepare data in an alphanumeric field
for conversion into a date field. If the data were in the form
MM-DD-YY, Paradox would not allow you to restructure the table.
The parse routine could then be used to break up MM-DD-YY using
the dash as a delimiter. The field could then be reassembled with
slashes which Paradox would allow to be converted into a date
field.
The routine completes its work by creating an array called
parse.a. The array is not declared as private, so it is available
for other routines to call. Count.n receives the number of
elements in the array.
Since the array remains global, it is wise for the programmer to
release it when its work is complete to free up additional
memory.
It is also wise to avoid using the variable parse.a to avoid
conflict with the array.
47
picktable
Description: Presents the user with a dialog box that can be
used to select a table from the current directory.
Syntax: chosen.a = picktable.a ()
Where: chosen.a . receives the name of the table chosen.
The routine pops up a dialog box with a listing of the tables in
the current directory. It then returns to a variable the name of
that table. It does not place the table on the workspace.
A simple change could be made in the code to allow the programmer
to tell the routine what directory to present, however to keep
things simple, the current directory was chosen as the default.
48
popcal
Description: A pop-up calendar program written entirely in PAL.
Syntax: popcal.u ()
The routine puts a window showing the current month in the center
of the screen.
The user may press the left and right arrow keys to move forward
or behind in months. The user presses the ESC key to leave the
routine. The system date must be accurately set for the routine
to work correctly.
The routine was intended to be called from a SETKEY command,
however it can just as easily be called from a program when the
user is asked to input a number.
49
popval
Description: A pop-up valcheck menu that allows the user to
select an appropriate valcheck for the current field.
Syntax: popval.a ()
The routine presents a menu of 22 possible valchecks and sets the
valcheck for the current field.
The user presses the arrow keys to move the light bar to the
appropriate valcheck, then presses ENTER to select it.
Once selected the routine sets that valcheck for the current
field. The user must be in edit mode for the routine to work.
50
postal
Description: A routine to put an address in accepted postal form
Syntax: newaddress.a = postal.a(address.a)
Where: newaddress.a receives the corrected address
address.a . is the address to be corrected
While validity checks can be used to force data entry people to
enter an address into separate fields correctly, this process can
slow workers down. Sometimes it may be faster to allow workers to
enter the address as a full line and have the programmer make the
corrections.
Postal handles that task. While no postal correction software is
perfect, the routine can handle more address types and return an
address that is postal correct.
After correction, the programmer can then parse the address and
place it into individual fields, if desired.
The routine requires the use of the street database included with
the package. This serves as the look-up for correct street names.
The only known problem with the routine will come if a street
name is the same as a street type.
For example, an address of 619 East Center Street will be
returned as 619 E Ctr St. Should these problems be too great for
the user, the problem street names can be edited out of the
table.
Likewise, if changes are needed that aren't included in the
table, they can be added.
51
printreport
Description: Asks the user if the report is to be printed to a
printer, the screen or a file, then prints the report.
Syntax: test.l = printreport.l(tablename.a, reportname.a)
Where: test.l . . is true if the report printed without error
tablename.a is the name of the table hosting the report
reportname.a is the report number
When a user requests a report, printreport.l can handle all the
details of printing it. It asks the user if it is to be printed
to a printer, the screen or a file.
If the user chooses printer, the routine checks to printer to
make sure it is ready. If the user asks for a file, the routine
prompts the user for the file name and checks to see if it
already exists.
The routine returns true if the report was printed or false if
the user cancelled the effort.
52
proper
Description: Formats a string to proper case.
Syntax: newstring.a = proper.a(oldstring.a)
Where: newstring.a is the string formatted to proper case.
oldstring.a is the string to be formatted.
The routine is helpful in fixing names provided in all caps.
However the routine will have problems with names such as
MacDonald which will become Macdonald.
This can be fixed with a look-up table if you know the problems
names you will encounter. A description of that solution is
included within the script.
The script does successfully handle names such as McCoy and
O'Donnell.
53
recordrange
Description: Moves records from the current table into a new
table
Syntax: recordrange.u (start.n, stop.n)
Where: start.n . . is the first record to copy
stop.n . . is the last record to copy
There may be times when you want to move a series of records from
one table to another when those records have no relation other
than that they are consecutive.
It is nearly impossible to query for such an event, so
recordrange was written to make that job easier.
You call recordrange with the number of the first record you want
to move and the number of the last record you want to move. The
procedure then creates a table with the same structure as the
current table.
It moves to the first record to be moved, moves it to the new
table, the continues the process until all records are copied.
The new table will be named with the first six characters of the
current table followed by an underline and a number.
The procedure checks to see if that table exists, if so, it
generates another number. If the procedure must go past nine, it
truncates the original table name to five characters.
For example the table "Mailing" would become "Mailin_1" or
"Maili_10" if nine numbers had been used.
54
remblanks
Description: Removes all spaces from a string.
Syntax: newstring.a = remblanks.a(oldstring.a)
Where: newstring.a receives a string without blank spaces
oldstring.a is a string that may contain blanks
Removes all ASCII 32 characters from a string.
55
replace
Description: A routine that will search for a replace a string in
an alphanumeric field.
Syntax: replace.u
Replace will search through an entire table and replace any
chosen string with another string. The search will take place
only in the current field.
The routine allows for confirmation of each replacement or will
globally replace the strings without confirmation. The choice can
be toggled by the user using the TAB key.
The routine should not be confused with a CHANGETO query. For
changing a complete field, the CHANGETO will not only be more
efficient, but could also be much faster, depending upon the size
of the table.
Replace finds its strength in changing only part of a string. For
example it might be used to change dashes in a date to slashes in
preparation for restructuring a field from alphanumeric to date.
56
replacechar
Description: Searches through a string and replaces on character
with another
Syntax: replacechar.a(search.a, find.a, replace.a)
Where: search.a . is the string to search
find.a. . . is the string to find within search.a
replace.a . is the string to exchange with search.a
The routine replaces all occurrences of a string with a new
string. Unlike the replace routine, this does not seek
confirmation nor does it have any user interface.
57
restorerec
Description: Restores last record deleted using the delrec.u
routine.
Syntax: restorerec.u ()
The most recent record deleted using the delrec.u routine is held
in an array in memory until the user leaves Paradox.
The restorerec.u routine will restore that record even if the
editing session has ended and the user is in main mode. The table
must be on the workspace at the time the restoration is
requested, but it may have been removed previously.
The routine will work only for the most recent deletion.
58
rtrim
Description: Trims trailing spaces from a string.
Syntax: newstring.a = rtrim.a (oldstring.a)
Where: newstring.a receives a string without trailing spaces
oldstring.a is a string that may have trailing spaces
The routine will trim all trailing ASCII 32 characters from a
string. It will be faster than lrtrim.a if only trailing are
expected.
59
search
Description: A routine to search for any value in any field
type.
Syntax: search.u ()
The routine will allow the user to enter up to 50 characters
which can be sought in the current field.
The routine also offers the choice of an exact or similar match.
The choice is toggled by pressing the TAB key.
Exact searches are possible in all field types, but similar
searches are allowed only in alphanumeric fields.
The routine allows for a search, then a continuation of the
search using the familiar Paradox ALT-Z key combination.
60
sortarraya
Description: Sorts a Paradox array into ascending order.
Syntax: sortarraya.v (arrayname.r)
Where: arrayname.r is the array variable declared in the ARRAY
statement
The routine sorts an array into ascending order. This is
particularly useful when an array is going to be used in
SHOWARRAY or PICKARRAY call.
The routine sorts only assigned elements and assumes they have
been assigned consecutively. For example if if an array has been
declared to 100 elements, but only 40 have been used, the routine
will sort the 40 and place all blank elements at the end. It also
assumes the assigned elements are 1-40. If any of those elements
are blank, they will be included in the sort.
61
sortarrayd
Description: Sorts a Paradox array into decending order.
Syntax: sortarrayd.v (arrayname.r)
Where: arrayname.r is the array variable declared in the ARRAY
statement
The routine sorts an array into decending order. This is
particularly useful when an array is going to be used in
SHOWARRAY or PICKARRAY call.
The routine sorts only assigned elements and assumes they have
been assigned consecutively. For example if if an array has been
declared to 100 elements, but only 40 have been used, the routine
will sort the 40 and place all blank elements at the end. It also
assumes the assigned elements are 1-40. If any of those elements
are blank, they will be included in the sort.
62
statusbar
Description: A moving bar and message that graphically shows the
user how far a process has progressed.
Syntax: statusbar.u(msg.a, row.n, col.n, length.n, counter.n,
start.n, end.n)
Where: msg.a . . . is the message to display above the bar
row.n . . . is the row where the bar is to be displayed
col.n . . . is the column where the bar is to begin
length.n . is the length of the bar
counter.n . is the counter position in the loop
start.n . . is the beginning of the loop
end.n . . . is where the loop will end
Despite the number of variables required in a call to statusbar,
it is very easy to use.
The routine is intended to be used in a FOR/NEXT or
WHILE/ENDWHILE loop where the number of passes through the loop
are known.
Here is a sample of how statusbar.u might be used:
FOR x from 1 to 500
statusbar.u("Processing data", 5, 1, 20, x, 1,
500)
....
....
....
ENDFOR
The routine will calculate the percentage of how far the loop the
counter gone, apply that percentage to the length of the bar,
then display the bar. With each pass through the loop, the
calculation is updated, allowing the use of the STEP statement in
the FOR loop.
While the routine will handle any length for the bar up to one
screen width.
63
striphigh
Description: Strips all ASCII characters above 126 out of a
string.
Syntax: newstring.a = striphigh.a(oldstring.a)
Where: newstring.a receives a string of ASCII characters below
127
oldstring.a is a string that may contain ASCII
characters above 126
The routine will strip all high ASCII characters out of a string
that may cause problems with some printers.
64
syscheck
Description: Displays a dialog box with information about the
computer system.
Syntax: syscheck.u ()
Displays a dialog box giving information about memory, the
hardware being used and the current Paradox state.
It's good for user information and to help diagnosis system
problems when on the telephone with a user.
65
textbox
Description: Prompts the user to enter a line of text and
formats it to all caps, all lower case or with only the first
letter of each word capitalized.
Syntax: newstring.a = textbox.a(headline.a, length.n, styl.n)
Where: newstring.a receives a formatted string of text
headline.a is the headline to place on the box
length.n . is the number of characters to be entered
styl.n . . is the style to format the new text
Using a dialog box, textbox.a prompts the user for a one line
text string. A headline can be put on the box to prompt the user
as to what text to enter. The length.n variable determines how
long the string can be.
Although the routine can handle strings of up to 80 characters,
the dialog box runs off the screen. The routine will look best
when used with lengths of 64 or less.
If styl.n is set to 1, the text will be returned to newstring.a
in all capitals. If it is set to 2, the string will be returned
in all lower case. If it is set to 3, the first letter of each
word will be capitalized. If any other number is used, the text
will be returned unaltered.
The routine also uses the lrtrim.a function to trim any leading
or trailing from the string.
If the user exits without entering any text, the routine returns
a value of false.
66
timeadd
Description: Adds two time values.
Syntax: totaltime.a = timeadd.a(timevalue1.a, timevalue2.a)
Where: totaltime.a is the total of timevalue1.a plus
timevalue2.a
Paradox allows you to capture the current time, but it does not
allow math with it. This routine allows you to add two time
values. It has two companion routines. One allows subtraction
while the other, hrs2days, tells you the number of days which
accrued if the addition results in more than 24 hours.
The timevalues must be strings in the HH:MM:SS format to be used
in this routine.
67
time2num
Description: Converts the time in HH:MM:SS format to a number.
Syntax: timenum.n = time2num.n(time.a)
Where: timenum.n . receives the time number value
time.a . . is the time in HH:MM:SS format
Because numbers take up less space than the time format in a
Paradox table, it may be worthwhile to store the time as a
number. This routine converts a standard time format to the
number of milliseconds since midnight.
The format is the same as used by the Paradox TICKS () function.
68
timesub
Description: Subtracts one time value from another.
Syntax: newtime.a = timesub.a(timevalue1.a, timevalue2.a)
Where: newtime.a . receives the result of subtraction
timevalue2.a from timevalue1.a
The routine subtracts the second time value from the first time
value. The values must be in the HH:MM:SS format.
The routine allows negative results and returns a nine position
value instead of the expected eight positions. Programmers using
this routine should check for a negative value before attempting
to plug the results of the routine into an 8-character field
unless the results will always be positive.
69
uniquename
Description: Generates a unique string that can be used as a
file name.
Syntax: filename.a = uniquename.a ()
Where: filename.a receives the new file name.
After generating an answer table, the table must often be renamed
while other queries are done. These names may be hard-coded, but
then the program must always check to see if such a file already
exists.
The routine generates a five-digit number, checks to see if a
file by that name exists, then returns the number if no such file
exists. The name may then be used as a new name for the answer
table.
The name can also be reused later if the table is to be deleted.
The returned string carries no file name extension, so the string
can be used to name any kind of file.
The extra-cautious programmer would also check the file name
against the ISTABLE () command to make sure no tables exist. In
some situations, tables created during a Paradox session may not
yet be stored on disk. The check is not included in the routine
in case the name is to be used for a different purpose.
This eventuality, however, is rare unless many temporary tables
were being created as part of the program.
70
waitkeypress
Description: Creates a pause until the user presses a key.
Syntax: waitkeypress.v ()
or
charpicked.a = waitkeypress.v ()
Where: charpicked.a is the key pressed
The routine is used to halt program execution until a key is
pressed. If knowing the key is important, the function version of
the routine can be used.
71
wipes
Description: A demonstration program to show how wipes can be
added to a program.
Syntax: wipes.u ()
Wipes is included only to show that wipes can be done with PAL.
The source code shows how wipes can be written into programs.
72
workwindow
Description: Places a floating window on the screen telling the
user that work is being done behind the scenes.
Syntax: windowhandle = workwindow.n ()
Where: windowhandle receives the handle of the window opened.
The routine puts a floating window in the center of the screen
with the flashing message: Working.
Because the window is floating, it will remain at the top of all
other windows. It is then up to the programmer to close the
window when it is no longer needed. That is done by calling the
window select command to make window current, then using the
window close command.
73